/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package javaapplication6.ControlLayer;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import javaapplication6.DomainLayer.Customer;
import javaapplication6.DomainLayer.StatisticsLogOrders;
import javaapplication6.DomainLayer.OrderRentProduct;
import javaapplication6.DomainLayer.OrderRentRecords;
import javaapplication6.DomainLayer.RentProduct;
import javaapplication6.DomainLayer.StatisticsOfCompany;

/**
 *
 * @author meydlo
 */
public class OrderRentControl {

    private long orderId=0;

    private OrderRentRecords orderRentRecords=OrderRentRecords.getOrderRentRecords();
    private RentControl rentControl=new RentControl();
    private CustomerControl customerControl=new CustomerControl();


    //define How many of one product put to Basket, returns products of one type cust want to buy (noOfOneType)
    public OrderRentProduct addProduct(long idOfCustomer,long idOfProduct, int noOfOneType, int duration)
    {
        //define rentproduct
        RentProduct rentProduct=rentControl.findRentProduct(idOfProduct);

        //create and set orderRentProduct
        OrderRentProduct orderRentProduct=setOrderRentProduct(rentProduct,noOfOneType,idOfCustomer, duration);

        return orderRentProduct;
    }

    //int index= ordinal number of rentproduct in Arraylist<OrderRentProduct>
    public double getTotalPriceOfOneType(OrderRentProduct orderRentProduct,boolean isDiscount)
    {
        //declaring variables of orderRentProduct necessary to count prices
        double price=orderRentProduct.getPrice();
        double discount=orderRentProduct.getDiscount();
        int noOfOneType=orderRentProduct.getNoOfOneType();

        //sum:
        double totalPrice=price*noOfOneType;

        if(isDiscount==true){
            double totalPriceAfterDiscount=((totalPrice)*((100-discount)/100));
            return totalPriceAfterDiscount;
        }
        return totalPrice;
    }


    //return how much the customer has to pay for order
    public double getTotalPriceOfBasket(ArrayList<OrderRentProduct> orderRentProductList,boolean isAfterDiscount)
    {
        //declare total price of all products in basket
        double totalPrice=0;

        //counting (no discount)
        if(isAfterDiscount==false){
            for(int i=0;i<orderRentProductList.size();i++){
                OrderRentProduct orderRentProduct=orderRentProductList.get(i);
                totalPrice+=getTotalPriceOfOneType(orderRentProduct,false);
            }
        }
        //if we want to getTotal price of basket after discount
        else if(isAfterDiscount==true){
            for(int i=0;i<orderRentProductList.size();i++){
                OrderRentProduct orderRentProduct=orderRentProductList.get(i);
                totalPrice+=getTotalPriceOfOneType(orderRentProduct,true);
            }
        }
        return totalPrice;
    }

    public void printOrderRentProduct(OrderRentProduct orderRentProduct)
    {
        //set variables (name: noOfOneType: price: discout:)
        String name=orderRentProduct.getName();
        int noOfOneType=orderRentProduct.getNoOfOneType();
        double price=orderRentProduct.getPrice();
        double  discount=orderRentProduct.getDiscount();
        Date beginning=orderRentProduct.getBeeginning();
        long duration=orderRentProduct.getDuration();

        System.out.println();

        //set variables of one kind
        double moneyForOneKind=getTotalPriceOfOneType(orderRentProduct,false);
        double moneyForOneKindAfterDiscount=getTotalPriceOfOneType(orderRentProduct,true);

        System.out.println("Product name:"+name+
            " | amount: "+noOfOneType+
            " | price: "+price+
            " | discount"+discount+
            "\nBeginning: "+beginning+
            " | duration: "+duration+
            "\ntotal: "+moneyForOneKind+
            "\ntotal after discount: "+moneyForOneKindAfterDiscount
            );
    }
    public void printBasket(ArrayList<OrderRentProduct> orderRentProductList)
    {
        //declare here because loop
        double totalOfBasket=0;
        double totalOfBasketAfterDiscount=0;
        OrderRentProduct orderRentProduct=null;

        //iterate over whole basket
        for(int i=0;i<orderRentProductList.size(); i++){

            //declaring product from where we gain informations
            orderRentProduct=orderRentProductList.get(i);

            //set variables of basket
            totalOfBasket=getTotalPriceOfBasket(orderRentProductList, false);
            totalOfBasketAfterDiscount=getTotalPriceOfBasket(orderRentProductList,true);

        }
        if(totalOfBasket!=0){
            //printing informations for One product;
                printOrderRentProduct(orderRentProduct);
            System.out.println("--------------------------"+
                    "\nTotal price: "+totalOfBasket+
                    "\nyou pay (after discount): "+totalOfBasketAfterDiscount+
                    "\nyou save: "+(totalOfBasket-totalOfBasketAfterDiscount)+
                    "\n############################################"
            );
        }
    }


    //put to hashmap in (OrderRecords) (id of order)+(basket)
    public void storeOrderToHashMap(ArrayList<OrderRentProduct> orderRentBasketList)
    {
        orderId+=1;
        Long idLong=new Long(orderId);
        orderRentRecords.getOrderRentHashMap().put(idLong, orderRentBasketList);
    }

    //confirm or cancel ordering
    public void confirmOrder(ArrayList<OrderRentProduct> orderRentProductList, boolean isConfirmed)
    {
        if(isConfirmed==true){

            //set goods(ArrayList<OrderRentProduct>) to (HashMap<Long, ArrayList<OrderRentProduct> >)
            storeOrderToHashMap(orderRentProductList);

            
            System.out.println("Order was registered!");
            System.out.println("\n##### Your order ID: "+getOrderId()+" #####\n");
        }
        else{
            orderRentProductList.clear();
            System.out.println("Order was canceled");
        }
    }


     public void confirmToBuy(long orderId, boolean isRented){

        //declare OrderHashMap
        HashMap<Long, ArrayList<OrderRentProduct>> orderHashMap=orderRentRecords.getOrderRentHashMap();

        //extract orderRentProductList from HashMap
        ArrayList<OrderRentProduct> orderRentProductList=orderHashMap.get(orderId);

        //if C want to buy -> order in (OrderRentHashMap) -> moving to -> log (logOrdersHashMap)
        if(isRented==true){
            System.out.println("Rented successfully");
        }
        //(return goods back to stok) && (remove order from HashMap)
        else{
            //return products to ArrayList<RentProduct>
            returnProductsToProductList(orderRentProductList);

            //remove order From OrderHashMap
            orderHashMap.remove(orderId);

            System.out.println("Renting successfully canceled");
        }



    }


    public void removeAllProductsfromProductList(ArrayList<OrderRentProduct> orderRentProductList)
    {
        for(int i=0; i<orderRentProductList.size(); i++){

            //declare particular orderRentProduct and RentProduct
            OrderRentProduct orderRentProduct=orderRentProductList.get(i);
            RentProduct rentProduct=rentControl.findRentProduct(i);

            //set id of product to remove
            long idOfProduct=orderRentProduct.getId();

            //how many to remove
            int numToRemove=orderRentProduct.getNoOfOneType();

            //remove (each num of product) of (each product which exist in ArrayList<OrderRentProduct>)
            removeProductFromProductList(idOfProduct, numToRemove);
        }


    }

    public void removeProductFromProductList(long idOfProduct,int numToRemove)
    {
        RentProduct rentProduct=rentControl.findRentProduct(idOfProduct);
        //how meny is in stok
        int noOfProduct=rentProduct.getNoOfOneType();

        //set rest goods in stok
        int rest=noOfProduct-numToRemove;


        //set value in RentProductRecords
        rentProduct.setNoOfOneType(rest);
    }

    public void addRentProductToRentProductList(long idOfProduct,int numToAdd, RentProduct rentProduct)
    {
         //how meny is in stok
        int noOfProduct=rentProduct.getNoOfOneType();

        //set rest goods in stok
        int goodsAfterAdded=noOfProduct+numToAdd;

        //set value in RentProductRecords
        rentProduct.setNoOfOneType(goodsAfterAdded);
    }


    public void returnProductsToProductList(ArrayList<OrderRentProduct> orderRentProductList)
    {
        for(int i=0; i<orderRentProductList.size(); i++){

            //declare particular orderRentProduct from where gain inf
            OrderRentProduct orderRentProduct=orderRentProductList.get(i);

            //id of product
            long idOfProduct=orderRentProduct.getId();

            RentProduct rentProduct=rentControl.findRentProduct(idOfProduct);

            //how many to add
            int numToAdd=orderRentProduct.getNoOfOneType();

            //how meny is in stok
            int noOfProduct=rentProduct.getNoOfOneType();

            //set rest goods in stok
            int goodsAfterAdded=noOfProduct+numToAdd;

            //set value in RentProductRecords
            rentProduct.setNoOfOneType(goodsAfterAdded);

        }
    }

    //return true if is empty
    public boolean isEmptyBasket(ArrayList<OrderRentProduct> orderRentProducts)
    {
        if(orderRentProducts.isEmpty()){
            return true;
        }
        else{
            return false;
        }
    }

    //declaring and returning (OrderRentProduct)
    public OrderRentProduct setOrderRentProduct(RentProduct rentProduct, int noOfOneType, long customerId, int duration)
    {
        //create object of OrderRentProduct
        OrderRentProduct orderRentProduct=new OrderRentProduct();

        //create instance variables (preparing for set to orderRentProduct)
        long productId=rentProduct.getId();
        String nameOfProduct=rentProduct.getName();
        String description=rentProduct.getDescription();
        double price=rentProduct.getPrice();
        double discount=getBiggerDiscount(customerId, productId);

        //set informations to orderRentProduct;
        orderRentProduct.setId(productId);
        orderRentProduct.setName(nameOfProduct);
        orderRentProduct.setPrice(price);
        orderRentProduct.setNoOfOneType(noOfOneType);
        orderRentProduct.setCustomerId(customerId);
        orderRentProduct.setDuration(duration);
        orderRentProduct.setDescription(description);
        orderRentProduct.setDiscount(discount);



        return orderRentProduct;
    }

    public boolean orderExist(long orderId)
    {
        HashMap<Long, ArrayList<OrderRentProduct>> orderRentHashMap=orderRentRecords.getOrderRentHashMap();

            if(orderRentHashMap.get(orderId)!=null){
                return true;
            }

        return false;
    }

    public boolean enoughGoodsInStok(int noOfWanted, RentProduct rentProduct)
    {
        int noOfGoodsInStok=rentProduct.getNoOfOneType();

        if(noOfGoodsInStok>=noOfWanted){
            return true;
        }
        else{
            return false;
        }
    }

    public long getOrderId() {
        return orderId;
    }

    
    public HashMap<Long, ArrayList<OrderRentProduct>> getOrderRentHashMapC(){
        HashMap<Long, ArrayList<OrderRentProduct>> orderRentHashMap =orderRentRecords.getOrderRentHashMap();
        return orderRentHashMap;
    }

    public void setBeginningOfOrder(ArrayList<OrderRentProduct> orderRentProductList)
    {
        Date date=new Date();

        for(OrderRentProduct orderRentProduct : orderRentProductList){
            orderRentProduct.setBeginning(date);
        }
    }


    //count how much is customer late to return goods
    public long howMuchExpired(Date beginning,int duration)
    {
        Date date=new Date();
        long beginningLong=beginning.getTime();
        
        long actualTime=date.getTime();

        //counting in days
        duration=duration*(1000*60*60*24);

        //what is the time till customer has to return goods
        long expiretThisTime=(beginningLong+duration);

        //if expiration (is positive(+) || 0) => customer return goods on the time
        long expiration=(actualTime - expiretThisTime);
        long expirationInDays=expiration/(1000*60*60*24);

        
        return expirationInDays;
    }

    
    public void printRentReturnBill(HashMap<Long, ArrayList<OrderRentProduct>> orderRentHashMap, long IdOfOrder)
    {
        //extracting orderProduct list from HashMap of orders
        ArrayList<OrderRentProduct> orderRentProductList=currentArrayListRentFromHashMap(orderRentHashMap, IdOfOrder);

        //setting how much will be person pay
        double beforeDiscount=getTotalPriceOfBasket(orderRentProductList, false);
        double afterDiscount=getTotalPriceOfBasket(orderRentProductList, true);

        System.out.println("you pay: "+getTotalPriceOfBasket(orderRentProductList, true)+
                "you pay extra: "+getExtraChargedWholeBasket(orderRentProductList));
    }


    public ArrayList<OrderRentProduct> currentArrayListRentFromHashMap(HashMap<Long, ArrayList<OrderRentProduct>> orderRentHashMap,long idOfOrder)
    {

        //getting Values for Iterate
        Iterator it = orderRentHashMap.keySet().iterator();

        while(it.hasNext()){

            //getting orderId from HashMap
            Long orderIdHere=(Long) it.next();

            if(idOfOrder==orderIdHere){

                //extract arraylist from hashmap
                ArrayList<OrderRentProduct> orderRentProductList=orderRentHashMap.get(orderIdHere);

                return orderRentProductList;
            }

        }

        return null;
    }

    public ArrayList<ArrayList<OrderRentProduct>> getArrayListsFromHashMap(HashMap<Long, ArrayList<OrderRentProduct>> orderRentHashMap)
    {

        //getting Values for Iterate
        Iterator it = orderRentHashMap.keySet().iterator();

        //created arraylist hich will be contains ordered Baskets
        ArrayList<ArrayList<OrderRentProduct>> arrayListsFromHashMap=new ArrayList<ArrayList<OrderRentProduct>>();

        while(it.hasNext()){

            //getting orderId from HashMap
            Long orderIdHere=(Long) it.next();

            //extract arraylist from hashmap
            ArrayList<OrderRentProduct> orderRentProductList=orderRentHashMap.get(orderIdHere);

            //put extracted arraylist to arraylist which contains of arraList<orderRentpreoduct>
            arrayListsFromHashMap.add(orderRentProductList);
        }

        return arrayListsFromHashMap;
    }


    //!!! purpose put (HashMap<Long, ArrayList<OrderRentProduct>>) in header as parameter-> to use for statistics as well
    public void printOrdersHashMap(HashMap<Long, ArrayList<OrderRentProduct>> orderRentHashMap ,boolean detailed)
    {
        //extract ArrayList from HashMap
        ArrayList<ArrayList<OrderRentProduct>> arrayListsFromHashMap=getArrayListsFromHashMap(orderRentHashMap);

        //how much orders
        int noOfOrders=arrayListsFromHashMap.size();


        if(detailed){

            //print extract for each basket
            for(ArrayList<OrderRentProduct> orderRentProduct : arrayListsFromHashMap){
                printBasket(orderRentProduct);
            }
        }
        System.out.println("number of orders: "+noOfOrders);
    }


    //
    public double getextraCharged(int noOfOneType, double price,long howMuchExpired)
    {
        double extraCharged=price*1.5*noOfOneType*howMuchExpired;
        return extraCharged;
    }

    //return how much has cutomer pay for later returning.
    public double getExtraChargedOneType(OrderRentProduct orderRentProduct)
    {
        //declaring { (when customer ordered product)+(how much of one type)+(duration) }
        //from orderedRentProduct
        Date beginning=orderRentProduct.getBeeginning();
        int noOfOneType=orderRentProduct.getNoOfOneType();
        int duration=orderRentProduct.getDuration();

        //count expiration time
        long expired=howMuchExpired(beginning, duration);

        //
        if(expired<=0){
            return 0;
        }
        else{
            //count how much has customer pay for this one type of goods
            double extraCharged=getextraCharged(noOfOneType, duration,expired);

            return extraCharged;
        }
    }


    public double getExtraChargedWholeBasket(ArrayList<OrderRentProduct> orderRentProductList)
    {
        //extract one product from list
        OrderRentProduct orderRentProduct=orderRentProductList.get(0);

        //declare information for comparing
        Date beginning=orderRentProduct.getBeeginning();
        int duration=orderRentProduct.getDuration();

        //count expiration time (+ = on time)
        long expiration=howMuchExpired(beginning, duration);

        //
        double totalExtra=0;

        //cust is on the time
        if(expiration<=0)
        {
            return 0;
        }
        //cust is late
        else{
            for(OrderRentProduct orp : orderRentProductList){
                double extracharged=getExtraChargedOneType(orp);
                totalExtra+=extracharged;
            }
            return totalExtra;
        }

    }

    public void returned(long orderId)
    {
        //define orderRentProductList
        HashMap<Long, ArrayList<OrderRentProduct>> orderRentHashMap=orderRentRecords.getOrderRentHashMap();
        ArrayList<OrderRentProduct> orderRentProductList=orderRentHashMap.get(orderId);

        double payment=getTotalPriceOfBasket(orderRentProductList, true);
        double extraPay=getExtraChargedWholeBasket(orderRentProductList);

        //putting to statistics:
        StatisticsOfCompany statisticsOfCompany=StatisticsOfCompany.getStatisticsOfCompany();
        statisticsOfCompany.setExtraMoney(extraPay);
        statisticsOfCompany.setMoneyFromRent(payment);
        
        //returning goods in list back to stok
        returnProductsToProductList(orderRentProductList);

         //define LOgOrdersHashMap
        StatisticsLogOrders logOrders=StatisticsLogOrders.getLogOrders();
        HashMap<Long, ArrayList<OrderRentProduct>> logOrdersRentHashMap=logOrders.getLogOrdersRentHashMap();

        //print whole extra charged
        System.out.println("you pay extra: "+extraPay);

        //add basket to LogList
        logOrdersRentHashMap.put(orderId, orderRentProductList);

        //remove order From OrderHashMap
        orderRentHashMap.remove(orderId);

        System.out.println("Goods successfully returned");
    }

    public double getBiggerDiscount(long customerId,long productId)
    {
        Customer customer=customerControl.findCustomer(customerId);
        RentProduct rentProduct=rentControl.findRentProduct(productId);

        //
        double customerDiscount=customer.getDiscount();
        double productDiscount=rentProduct.getDiscount();

        if(customerDiscount>productDiscount){
            return customerDiscount;
        }
        else{
            return productDiscount;
        }

    }


    public ArrayList<OrderRentProduct> extractBasket(long orderId)
    {
         //declare OrderHashMap
        HashMap<Long, ArrayList<OrderRentProduct>> orderHashMap=orderRentRecords.getOrderRentHashMap();

        //extract orderRentProductList from HashMap
        ArrayList<OrderRentProduct> orderRentProductList=orderHashMap.get(orderId);

        return orderRentProductList;
    }
}
